package com.heima.lock;

import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.concurrent.TimeUnit;

@RestController
public class StockController {
    @Autowired
    private StringRedisTemplate redisTemplate;

    @Autowired
    private WmLockMapper lockMapper;

    @Autowired
    private RedissonClient redissonClient;


    /**
     * 分布式锁：基于mysql实现
     *
     * @return
     */
    @GetMapping("/stock1")
    public String stock1() {
        //1. 获取分布式锁：谁能往表中成功的插入数据，那么就表示谁抢到了锁
        try {
            WmLock lock = WmLock.builder().mylock("DBlock").build();
            lockMapper.insert(lock);

            int stock = Integer.parseInt(redisTemplate.opsForValue().get("stock"));
            if (stock > 0) {
                stock--;
                redisTemplate.opsForValue().set("stock", stock + "");
                System.out.println("库存扣减成功，剩余库存：" + stock);
            } else {
                System.out.println("库存不足！！！");
            }

            //释放锁
            lockMapper.deleteById(lock.getId());
        } catch (Exception e) {
            System.out.println("没有抢到分布式锁");
        }

        return "OK";
    }


    /**
     * 分布式锁：基于redis实现
     *
     * @return
     */
    @GetMapping("/stock2")
    public String stock2() {
       /* //1. 获取分布式锁：谁能往redis中成功的插入数据，那么就表示谁抢到了锁
        //Boolean isLock = redisTemplate.opsForValue().setIfAbsent("lock", String.valueOf(Thread.currentThread().getId()));

        //给锁设置失效时间
        Boolean isLock = redisTemplate.opsForValue().setIfAbsent("lock", String.valueOf(Thread.currentThread().getId()),30, TimeUnit.SECONDS);

        if (isLock) {
            try {
                int stock = Integer.parseInt(redisTemplate.opsForValue().get("stock"));
                if (stock > 0) {
                    stock--;
                    redisTemplate.opsForValue().set("stock", stock + "");
                    System.out.println("库存扣减成功，剩余库存：" + stock);
                } else {
                    System.out.println("库存不足！！！");
                }
            } catch (Exception e) {
                e.printStackTrace();
            }finally {
                //释放锁: 只能释放自己的锁
                String value = redisTemplate.opsForValue().get("lock");
                if (StringUtils.isNotEmpty(value) && String.valueOf(Thread.currentThread().getId()).equals(value)) {
                    redisTemplate.delete("lock");
                }
            }

        } else {
            System.out.println("没有抢到分布式锁");
        }
*/
        //尝试获取分布式锁，谁能向redis插入数据，就表明获取到了锁,并增加锁失效时间
        Boolean islock = redisTemplate.opsForValue().setIfAbsent("lock", String.valueOf(Thread.currentThread().getId()), 30, TimeUnit.SECONDS);
        if(islock){
            //业务处理
            try {
                int stock = Integer.parseInt(redisTemplate.opsForValue().get("stock"));
                if(stock>0){
                    stock--;
                    redisTemplate.opsForValue().set("stock",stock+"");
                    System.out.println("库存扣减成功，剩余"+stock);
                }else {
                    System.out.println("库存不足");
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                //释放锁，只能是放自己的锁
                String value = redisTemplate.opsForValue().get("lock");
                //校验锁
                if(StringUtils.isNotEmpty(value) && String.valueOf(Thread.currentThread().getId()).equals(value)){
                    redisTemplate.delete("lock");
                }
            }
        }else {
            //未获取分布式锁
            System.out.println("未获取到分布式锁");
        }

        return "OK";
    }

    /**
     * 分布式锁：基于redisson实现
     * @param :
     * @return String
     */
    @GetMapping("/stock3")
    public String stock3(){
        //1. 获取分布式锁：谁能往redis中成功的插入数据，那么就表示谁抢到了锁
        //a.获取锁操作对象
        RLock lock = redissonClient.getLock("lock");

        //b.通过锁对象来尝试加锁
        lock.lock();   //默认所失效时间：30s  setnx lock 30 ThreadId
        try {
           int stock=Integer.parseInt(redisTemplate.opsForValue().get("stock"));
           if(stock>0){
               stock--;
               redisTemplate.opsForValue().set("stock",stock+"");
               System.out.println("库存扣减成功，剩余库存：" + stock);
           }else {
               System.out.println("库存不足！！！");
           }
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            //释放锁：只能释放自己的锁(底层自动判断)
            lock.unlock();
        }

        System.out.println("没有抢到分布式锁");
        return "OK";
    }
}